package ifm4j.core;

import org.w3c.dom.Document;
import org.w3c.dom.Element;


//import ifm4j.core.arguments.ConstraintTypeChangedArgs;
import ifm4j.core.featureModelInteraface.IFeature;
import ifm4j.core.featureRelationTypes.FMCrossTreeConstraintType;
import ifm4j.utils.Identifier;
import ifm4j.utils.InvalidIdentifierException;

public class CrossTreeConstraint {
	private static final String XML_ID = "ID";

    private static final String XML_TYPE = "CrossTreeConstraintType";

    private static final String XML_IDA = "IdentifyA";

    private static final String XML_IDB = "IdentifyB";

    public static final String NAME = "CrossTreeConstraint";

    private Identifier id;

    private FeatureModel featureModelOwner;

    private Identifier nodeIdA;

    private Identifier nodeIdB;

    private FMCrossTreeConstraintType type;

    protected CrossTreeConstraint(Identifier id, FMCrossTreeConstraintType type, Identifier idA, Identifier idB) {
        this.id = id;

        nodeIdA = idA;
        nodeIdB = idB;

        this.type = type;
    }

    /**
     * Get identifier
     * 
     * @return
     */
    public Identifier getIdentifier() {
        return this.id;
    }

    /**
     * get identifier of node A
     * 
     * @return
     */
    public Identifier getNodeIDA() {
        return this.nodeIdA;
    }

    /**
     * get identifier of node B
     * 
     * @return
     */
    public Identifier getNodeIDB() {
        return this.nodeIdB;
    }

    /**
     * get Tree Node A
     * 
     * @return
     */
    public IFeature getNodeA() {
        if (this.featureModelOwner == null) {
            return null;
        }
        return featureModelOwner.getFeatureNode(nodeIdA);
    }

    /**
     * get Tree Node B
     * 
     * @return
     */
    public IFeature getNodeB() {
        if (this.featureModelOwner == null) {
            return null;
        }
        return featureModelOwner.getFeatureNode(nodeIdB);
    }

    /**
     * get cross tree constaint type
     */
    public FMCrossTreeConstraintType getConstraintType() {
        return this.type;
    }

    /**
     * parse cross tree constraint to XML element
     * 
     * @return
     */
    public Element toXElem() {
        if (this.featureModelOwner == null) {
            return null;
        }
        Document xdoc = featureModelOwner.getXmlDocument();
        Element xelem = xdoc.createElement(NAME);
        xelem.setAttribute(XML_ID, this.id.toString());
        xelem.setAttribute(XML_IDA, this.nodeIdA.toString());
        xelem.setAttribute(XML_IDB, this.nodeIdB.toString());
        xelem.setAttribute(XML_TYPE, this.type.toString());

        return xelem;
    }

    /**
     * Parse XML to cross tree contraint
     * 
     * @param xelem
     * @return
     * @throws InvalidIdentifierException
     */
    public static CrossTreeConstraint xmlParser(Element xelem) throws InvalidIdentifierException {
        String idStr = xelem.getAttribute(XML_ID);
        String idAStr = xelem.getAttribute(XML_IDA);
        String idBStr = xelem.getAttribute(XML_IDB);
        String typeStr = xelem.getAttribute(XML_TYPE);

        Identifier id = new Identifier(idStr);
        Identifier idA = new Identifier(idAStr);
        Identifier idB = new Identifier(idBStr);
        FMCrossTreeConstraintType type = Enum.valueOf(FMCrossTreeConstraintType.class, typeStr);

        return new CrossTreeConstraint(id, type, idA, idB);
    }

    /**
     * 
     * @param fm
     */
    protected void setFeatureModelOwner(FeatureModel fm) {
        this.featureModelOwner = fm;
    }

    /**
     * Set cross tree constraint
     * 
     * @param type
     */
    public void setConstraintType(FMCrossTreeConstraintType type) {
//        ConstraintTypeChangedArgs args = new ConstraintTypeChangedArgs(this, type);
//        if (featureModelOwner != null) {
//            featureModelOwner.beforeProcess(this, args);
//        }
        this.type = type;

//        if (featureModelOwner != null) {
//            featureModelOwner.afterProcess(this, args);
//        }
    }
}
